package rkw.packager;

import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import rkw.communication.CommunicationService;
import rkw.database.DatabaseService;
import rkw.database.model.Election;
import rkw.database.model.UnsendVoterId;
import rkw.database.model.Vote;
import core.communication.message.VotersPackageMessage;
import core.communication.message.VotesPackageMessage;

@Service
public class PackagerServiceImpl implements PackagerService {

	private DatabaseService databaseService;
	private CommunicationService communicationService;

	private int unsendVotes = 0;
	private int unsendVoters = 0;

	private static int packageSize = 2;
	private static int votersSize = 2;

	public PackagerServiceImpl() {
	}

	public void setDatabaseService(DatabaseService databaseService) {
		this.databaseService = databaseService;
		unsendVotes = databaseService.getUnsendVotes().size();
		unsendVoters = databaseService.getUnsendVoterIds().size();

		if (unsendVotes >= packageSize)
			sendVotesPackage();

		if (unsendVoters >= votersSize)
			sendVotersPackage();
	}

	public void setCommunicationService(CommunicationService communicationService) {
		this.communicationService = communicationService;
	}

	@Override
	public void notifyAboutNewVote() {
		unsendVotes += 1;

		if (unsendVotes >= packageSize)
			sendVotesPackage();
	}

	@Override
	public void notifyAboutVoterVerification(String voterIdentificationField) {
		databaseService.storeUnsendVoterId(new UnsendVoterId(voterIdentificationField));
		unsendVoters += 1;

		if (unsendVoters >= votersSize)
			sendVotersPackage();
	}

	@Transactional
	@Override
	public void sendVotesPackage() {
		List<Vote> votes = databaseService.getUnsendVotes();

		Election election = databaseService.getStartedElection();

		if (election != null) {
			VotesPackageMessage message = new VotesPackageMessage(election.getIdentificationField(), communicationService.getServerURI());

			for (Vote vote : votes) {
				message.getVotes().add(vote.getVote());
				vote.setSend(true);
			}

			databaseService.updateVotes(votes);

			communicationService.send(message);

			unsendVotes -= votes.size();
		}
	}

	@Transactional
	@Override
	public void sendVotersPackage() {
		List<UnsendVoterId> voters = databaseService.getUnsendVoterIds();

		Election election = databaseService.getStartedElection();

		if (election != null) {
			VotersPackageMessage message = new VotersPackageMessage(election.getIdentificationField());

			for (UnsendVoterId unsendVoterId : voters) {
				message.getVotersIds().add(unsendVoterId.getIdentificationField());
			}

			databaseService.deleteUnsendVoterIds(voters);

			communicationService.send(message);

			unsendVoters -= voters.size();
		}
	}
}
